module EpuCode where

import E_Data
import E_API
import E_rawAPI
import EpuAlloc
import System.Cmd (system)
import System.Exit (ExitCode(..))
import System.Environment (getEnv)
import Text.Printf

data EpuDef = EpuDef { edName :: String, edVal :: Int}
    deriving Show 

makeDef :: EpuDef -> String
makeDef ed = printf "#define %s\t%d" (edName ed) (edVal ed)

makeEpuDefFile :: [EpuDef] -> [EpuAlloc] -> String -> IO()
makeEpuDefFile eds eas fn = writeFile fn $ unlines lines
    where lines = (map makeDef eds) ++ [""] ++ (map makeDecl eas)

run :: String -> [String]-> IO ExitCode
run cmd args = do
    let cmdline = cmd ++ (concat $ map ( " " ++) args)
    putStrLn cmdline
    system cmdline

egcc :: String -> IO ExitCode
egcc fn = do
    esdk <- getEnv "EPIPHANY_HOME"
    let eldf = esdk ++ "/bsps/current/fast.ldf"	-- was internal
    let args = ["-O3",
                "-std=c99",
                "-T " ++ eldf,
                fn ++ ".c",
                "-o " ++ fn ++ ".elf",
                "-le-lib",
                "-lm",
                "-ffast-math"]
    run "e-gcc" args

eobjcopy :: String -> IO ExitCode
eobjcopy fn = do
    let args = ["--srec-forceS3",
                "--output-target srec",
                fn ++ ".elf",
                fn ++ ".srec"]
    run "e-objcopy" args

runcmds :: [IO ExitCode] -> IO ExitCode
runcmds [] = return ExitSuccess
runcmds (cmd:cmds) = do
    st <- cmd
    case st of
        ExitSuccess -> runcmds cmds
        otherwise -> return st

c2srec :: String -> IO (Maybe EpuProg)
c2srec fnprefix = do
    st <- runcmds [egcc fnprefix, eobjcopy fnprefix]
    case st of
        ExitSuccess -> return $ Just $ EpuProg (fnprefix ++ ".srec")
        otherwise -> return Nothing

compileForEpu :: [EpuDef] -> [EpuAlloc] -> String -> IO (Maybe EpuProg)
compileForEpu eds eas fnprefix = do
    makeEpuDefFile eds eas (fnprefix ++ ".h")
    c2srec fnprefix
        
newtype EpuProg = EpuProg {getFileName :: String}
    deriving (Eq, Show)

epuLoadOneCore :: EpuProg -> GroupRef -> EpuPos -> IO Int
epuLoadOneCore (EpuProg srecFN) groupref pos =
    eLoadGroup srecFN groupref pos (GrpSize 1 1) e_false	-- program one core

epuRunOneCore :: EpuProg -> GroupRef -> EpuPos -> IO Int
epuRunOneCore (EpuProg srecFN) groupref pos =
    eLoadGroup srecFN groupref pos (GrpSize 1 1) e_true		-- program one core and run

epuLoadProg :: EpuProg -> GroupRef -> GrpSize -> IO Int
epuLoadProg (EpuProg srecFN) groupref gSize =
    eLoadGroup srecFN groupref (EpuPos 0 0) gSize e_false	-- program cores

epuRunProg :: EpuProg -> GroupRef -> GrpSize -> IO Int
epuRunProg (EpuProg srecFN) groupref gSize =
    eLoadGroup srecFN groupref (EpuPos 0 0) gSize e_true	-- program cores and run

epuStartOneCore :: GroupRef -> EpuPos -> IO ()
epuStartOneCore groupref (EpuPos row col) = do
    res <- e_start groupref row col
    return ()

epuStartGroup :: GroupRef -> IO ()
epuStartGroup groupref = do
    res <- e_start_group groupref
    return ()

testenv :: IO ()
testenv = do
    putStrLn "esdk1"
    esdk <- getEnv "EPIPHANY_HOME"
    putStrLn esdk
    putStrLn "esdk2"


--main = c2srec "whome"

